/**
 * @(#)RepositoryStructureAnalyzer.java, 2008-4-30.
 * Copyright 2008  Program Analysis Research Group(PARG),Institute of Software, Peking University.
 * All rights reserved.
 */
package edu.pku.sei.pgie.analyzer.internal;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

import edu.pku.sei.pgie.analyzer.core.Context;
import edu.pku.sei.pgie.analyzer.core.ICollector;
import edu.pku.sei.pgie.analyzer.core.SourceTreeVisitor;
import edu.pku.sei.pgie.beans.Structure;

/**
 * @author HeLi
 */
public class RepositoryStructureAnalyzer extends SourceTreeVisitor {
    HashMap<String, Structure> packageCache;
    Context context;
    ICollector collector;

    public RepositoryStructureAnalyzer(Context context) throws Exception {
        super();
        this.context = context;
        this.collector = context.getCollector();
        packageCache = new HashMap<String, Structure>();
    }

    public RepositoryStructureAnalyzer() {
        packageCache = new HashMap<String, Structure>();
    }

    @SuppressWarnings("unchecked")
    public boolean visit(ICompilationUnit compilationUnit) {
        System.out.println(compilationUnit.getElementName());
        String packageName;
        IPackageDeclaration[] declarations = null;
        try {
            declarations = compilationUnit.getPackageDeclarations();
        } catch (Exception e) {
            return false;
        }
        if (declarations == null || declarations.length < 1) {
            packageName = "default";
        } else {
            packageName = declarations[0].getElementName();
        }
        if (!packageCache.containsKey(packageName)) {
            return false;
        }

        Structure structure = (Structure) packageCache.get(packageName);
        try {
            IType[] types = compilationUnit.getTypes();
            for(IType type : types) {
                Structure child = new Structure();
                child.setName(type.getFullyQualifiedName());
                child.setChildren(null);
                child.setId(collector.nextStructureId());
                List children = structure.getChildren();
                if(children == null) {
                    children = new LinkedList();
                    structure.setChildren(children);
                }
                children.add(child);
            }
        } catch (JavaModelException e) {
            e.printStackTrace();
            return false;
        }

        return false;
    }

    public boolean visit(IPackageFragment packageFragment) {
        String name = packageFragment.getElementName();
        if(packageCache.containsKey(name))
            return true;
        Structure structure = new Structure();
        structure.setName(name);
        structure.setChildren(null);
        structure.setId(collector.nextStructureId());
        packageCache.put(name, structure);
        return true;
    }

    public void flushCache() {
        Set keySet = packageCache.keySet();
        Iterator iterator = keySet.iterator();
        try {
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                Structure structure = (Structure) packageCache.get(key);
                if (structure.getChildren() != null
                        && structure.getChildren().size() > 0)
                    if(collector != null)
                        collector.collect(structure);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
